package cn.thoughtworks.school.utils;

import cn.thoughtworks.school.entities.SocialAccount;
import cn.thoughtworks.school.entities.SocialToken;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Map;

public class WechatUtil {
  private static String DEFAULT_SOCIAL_WEIXIN_APP_ID = "wx0a53a01a2413d100";
  private static String DEFAULT_SOCIAL_WEIXIN_APP_SECRET = "2ec20a8b7e78d7b839c5796af08ad16f";
  private static String WECHAT_REDIRECT_URL = "http://school.thoughtworks.cn/learn/api/auth/redirection/";
  private static String WECHAT_BINDING_REDIRECT_URL = "http://school.thoughtworks.cn/learn/api/auth/wechatBind/";
  private static RestTemplate restTemplate = new RestTemplate();

  public static SocialAccount getSocialAccount(String code) throws IOException {
    SocialToken socialToken = requestWechatToken(code);

    Map<String, Object> wechatUser = requestWechatUserInfo(socialToken);

    return new SocialAccount().mergeSocialAccount(socialToken, wechatUser, "weixin");
  }

  private static Map<String, Object> requestWechatUserInfo(SocialToken socialToken) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    String openId = socialToken.getOpenid();
    String accessToken = socialToken.getAccess_token();

    String userInfoUrl = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s",
      accessToken,
      openId
    );

    restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("iso-8859-1")));
    restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
    String userObj = restTemplate.getForObject(userInfoUrl, String.class);
    mapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
    Map<String, Object> userInfo = mapper.readValue(new String(userObj.getBytes("ISO-8859-1"), "UTF-8"), new TypeReference<Map<String, String>>() {
    });

    return userInfo;
  }

  private static SocialToken requestWechatToken(String code) throws IOException {
    String tokenUrl = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
      DEFAULT_SOCIAL_WEIXIN_APP_ID,
      DEFAULT_SOCIAL_WEIXIN_APP_SECRET,
      code);

    String forObject = restTemplate.getForObject(tokenUrl, String.class);
    ObjectMapper mapper = new ObjectMapper();

    return mapper.readValue(forObject, new TypeReference<SocialToken>() {
    });
  }

  public static String getLoginRequestCodeUrl(String env) {
    return "https://open.weixin.qq.com/connect/qrconnect?" +
      "appid=" + DEFAULT_SOCIAL_WEIXIN_APP_ID +
      "&" +
      "redirect_uri=" + URLEncoder.encode(WECHAT_REDIRECT_URL+env) +
      "&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect";

  }
  public static String getWechatBindingRedirectUrl(String username) {
    return "https://open.weixin.qq.com/connect/qrconnect?" +
      "appid=" + DEFAULT_SOCIAL_WEIXIN_APP_ID +
      "&" +
      "redirect_uri=" + URLEncoder.encode(WECHAT_BINDING_REDIRECT_URL + username) +
      "&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect";

  }
}
